﻿using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace ClientApp.Classes.XtraTile
{
    public class ModuleChanger
    {
        [DllImport("gdi32.dll")]
        public static extern int BitBlt(IntPtr hDC, int x, int y, int nWidth, int nHeight, IntPtr hSrcDC, int xSrc,
                                        int ySrc, int dwRop);

        public const int SRCCOPY = 13369376;
        private bool showMainPanel = false;
        private int step = 120;
        private int indent = 0;
        private Form form;
        private Control mainPanel, modulePanel;
        private PictureBox draftPanel;
        private Timer timer, draftTimer;

        private int topOffset;
        private int bottomOffset;

        public ModuleChanger(Form form, Control mainPanel, Control modulePanel, int indent, int topOffset, int bottomOffset)
        {
            this.form = form;
            this.mainPanel = mainPanel;
            this.modulePanel = modulePanel;
            this.indent = indent;
            modulePanel.Visible = mainPanel.Visible = false;
            CreateDraftPanel();
            CreateTimers();

            this.topOffset = topOffset;
            this.bottomOffset = bottomOffset;
        }

        private void CreateDraftPanel()
        {
            this.draftPanel = new PictureBox {Parent = modulePanel, Visible = false, BorderStyle = BorderStyle.None};
        }

        private void CreateTimers()
        {
            timer = new Timer {Interval = 1};
            timer.Tick += mainTimer_Tick;

            draftTimer = new Timer {Interval = 1};
            draftTimer.Tick += draftTimer_Tick;
        }

        private void mainTimer_Tick(object sender, EventArgs e)
        {
            UpdateTimer(timer, false);
            if (showMainPanel && mainPanel.Location.X + step > 0)
            {
                mainPanel.Location = new Point(form.Padding.Horizontal + draftPanel.Width, form.Padding.Top + topOffset);
                mainPanel.Dock = DockStyle.Fill;
                modulePanel.Visible = false;
                TimerStop();
                return;
            }
            if (!showMainPanel && modulePanel.Location.X - step < form.Padding.Left)
            {
                modulePanel.Location = new Point(form.Padding.Horizontal + draftPanel.Width, form.Padding.Top + topOffset);
                modulePanel.Dock = DockStyle.Fill;
                mainPanel.Visible = false;
                TimerStop();
                return;
            }
            mainPanel.Location = new Point(mainPanel.Location.X + step*(showMainPanel ? 1 : -1),
                                           form.Padding.Top + topOffset);
            modulePanel.Location = new Point(modulePanel.Location.X + step*(showMainPanel ? 1 : -1),
                                             form.Padding.Top + topOffset);
        }

        private void TimerStop()
        {
            timer.Stop();
            //((TileControl)mainPanel).ResumeAnimation();
        }

        public void ShowPanel(bool showMainPanel, bool animation)
        {
            //animation = true;

            this.showMainPanel = showMainPanel;
            if (animation)
            {
                AnimateMainModules();
            }
            else
            {
                mainPanel.Visible = false;
                if (showMainPanel)
                {
                    modulePanel.Visible = false;
                    mainPanel.Dock = DockStyle.Fill;
                    mainPanel.Visible = true;
                }
                else if (DetailPanel != null)
                {
                    //BaseModule module = DetailPanel.Controls[0] as BaseModule;
                    //if (!animation && SplashScreenManager.Default == null && (module != null && module.AllowWaitDialog))
                    //    SplashScreenManager.ShowForm(form, typeof(DevExpress.XtraWaitForm.DemoWaitForm), false, true);
                    modulePanel.Dock = DockStyle.Fill;
                    modulePanel.Visible = true;
                    DetailPanel.Dock = DockStyle.Fill;
                    DetailPanel.Visible = true;
                    mainPanel.Visible = false;
                    //if (!animation && SplashScreenManager.Default != null && (module != null && module.AllowWaitDialog))
                    //    SplashScreenManager.CloseForm();
                }
            }
        }

        private void AnimateMainModules()
        {
            using (CreateDraftImage(form, showMainPanel ? modulePanel : mainPanel))
            {
                //((TileControl)mainPanel).SuspendAnimation();
                mainPanel.Dock = modulePanel.Dock = DockStyle.None;
                modulePanel.Size =
                    mainPanel.Size =
                    new Size(form.ClientSize.Width - form.Padding.Horizontal,
                             form.ClientSize.Height - form.Padding.Vertical - topOffset - bottomOffset);
                modulePanel.Visible = mainPanel.Visible = true;
                mainPanel.Location = new Point(showMainPanel ? -mainPanel.Width : form.Padding.Left,
                                               form.Padding.Top + topOffset);
                modulePanel.Location =
                    new Point(showMainPanel ? form.Padding.Left : form.Padding.Horizontal + mainPanel.Width,
                              form.Padding.Top + topOffset);

                StartTimer(timer, 100, 1);
            }
        }

        private PictureBox CreateDraftImage(Control parent, Control image)
        {
            PictureBox pb = new PictureBox
                                {
                                    Parent = parent,
                                    Visible = false,
                                    BorderStyle = BorderStyle.None,
                                    Image = GetControlImage(image),
                                    Dock = DockStyle.Fill
                                };
            pb.Visible = true;
            pb.BringToFront();
            return pb;
        }

        private Panel DetailPanel
        {
            get { return modulePanel.Controls[0] as Panel; }
        }

        private static Image GetControlImage(Control ctrl)
        {
            Graphics graphic = ctrl.CreateGraphics();
            Bitmap memImage = new Bitmap(ctrl.Width, ctrl.Height, graphic);
            Graphics memGraphic = Graphics.FromImage(memImage);
            IntPtr dc1 = graphic.GetHdc();
            IntPtr dc2 = memGraphic.GetHdc();
            BitBlt(dc2, 0, 0, ctrl.ClientRectangle.Width,
                ctrl.ClientRectangle.Height, dc1, 0, 0, SRCCOPY);
            graphic.ReleaseHdc(dc1);
            memGraphic.ReleaseHdc(dc2);
            return memImage;
        }

        //public void SetDraftImage()
        //{
        //    draftPanel.Image = GetControlImage(DetailPanel);
        //    DetailPanel.Visible = false;
        //    draftPanel.Size = new Size(modulePanel.ClientSize.Width + modulePanel.Padding.Horizontal,
        //                               modulePanel.ClientSize.Height - modulePanel.Padding.Vertical);
        //    draftPanel.Location = new Point(modulePanel.Padding.Left + modulePanel.Left,
        //                                    modulePanel.Top + DetailPanel.Top);
        //    draftPanel.Visible = true;
        //}

        private void draftTimer_Tick(object sender, EventArgs e)
        {
            UpdateTimer(draftTimer, DetailPanel.Location.X < DetailPanel.Width/3);
            if (DetailPanel.Location.X - indent - step < 0)
            {
                DetailPanel.Dock = DockStyle.Fill;
                draftPanel.Size = Size.Empty;
                draftPanel.Visible = false;
                draftTimer.Stop();
                return;
            }
            draftPanel.Location = new Point(draftPanel.Location.X - step, modulePanel.Top + DetailPanel.Top + topOffset);
            DetailPanel.Location = new Point(DetailPanel.Location.X - step, modulePanel.Top + DetailPanel.Top + topOffset);
        }

        //internal void ShowDraftPanel()
        //{
        //    DetailPanel.Dock = DockStyle.None;
        //    DetailPanel.Location = new Point(modulePanel.Padding.Left + modulePanel.Left + draftPanel.Width,
        //                                     modulePanel.Top + DetailPanel.Top);
        //    DetailPanel.Visible = true;

        //    StartTimer(draftTimer, 100, 1);
        //}

        private void UpdateTimer(Timer timer, bool slowdown)
        {
            if (!slowdown)
            {
                int interval = timer.Interval - 25;
                if (interval < 1) interval = 1;
                timer.Interval = interval;
                int dstep = step + 20;
                if (dstep > 120) dstep = 120;
                step = dstep;
            }
            else
            {
                timer.Interval += 5;
                if (timer.Interval > 50) timer.Interval = 50;
                int dstep = step - 20;
                if (dstep < 20) dstep = 20;
                step = dstep;
            }
        }

        private void StartTimer(Timer timer, int interaval, int step)
        {
            timer.Interval = interaval;
            this.step = step;
            timer.Start();
        }
    }
}
